<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
	<title>收货</title>
	<style>
		:root {
			--primary: #1677ff;
			--primary-dark: #0b5bd3;
			--bg: #f7f8fa;
			--text: #1f2329;
			--muted: #8a8f98;
			--border: #e5e6eb;
			--success: #16a34a;
			--danger: #ef4444;
		}
		* { box-sizing: border-box; }
		html, body { height: 100%; }
		body { margin: 0; background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Helvetica, Arial, sans-serif; }

		.container { min-height: 100%; padding: 12px 12px calc(16px + env(safe-area-inset-bottom)); }
		.header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
		.order { font-weight: 600; font-size: 16px; }
		.refresh-btn { margin-left: auto; background: var(--primary); color: #fff; border: 0; border-radius: 8px; padding: 8px 12px; font-size: 14px; }
		.refresh-btn:active { background: var(--primary-dark); }

		.card { background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 12px; }
		.list { display: flex; flex-direction: column; gap: 10px; }
		.item { display: flex; align-items: center; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 12px; background: #fff; }
		.item-title { font-weight: 600; font-size: 15px; }
		.item-sub { color: var(--muted); font-size: 12px; margin-top: 2px; }
		.item-qty { margin-left: auto; text-align: right; font-size: 12px; color: var(--muted); }
		.item-qty b { display: inline-block; min-width: 36px; color: var(--text); }
		.item-enter { background: var(--primary); color: #fff; border: 0; border-radius: 10px; padding: 8px 10px; font-size: 13px; margin-left: 8px; }
		.item-enter:active { background: var(--primary-dark); }

		.detail { display: none; gap: 12px; }
		.detail .head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
		.back { border: 1px solid var(--border); background: #fff; border-radius: 10px; padding: 8px 10px; font-size: 14px; }
		.code { font-weight: 700; font-size: 16px; }
		.stat { margin-left: auto; display: flex; gap: 10px; color: var(--muted); font-size: 12px; }
		.stat b { color: var(--text); }

		.scan { display: flex; gap: 8px; margin: 8px 0 12px; }
		.scan input { flex: 1; height: 44px; padding: 0 12px; border: 1px solid var(--border); border-radius: 10px; font-size: 15px; }
		.scan button { height: 44px; padding: 0 14px; border: 0; background: var(--primary); color: #fff; border-radius: 10px; font-size: 15px; }
		.scan button:active { background: var(--primary-dark); }

		.tabs { display: flex; gap: 6px; background: #fff; padding: 6px; border: 1px solid var(--border); border-radius: 12px; }
		.tab { flex: 1; text-align: center; padding: 10px; border-radius: 10px; font-size: 14px; color: var(--muted); background: #f7f8fa; }
		.tab.active { color: #fff; background: var(--primary); }

		.sn-list { margin-top: 10px; }
		.sn-ul { list-style: none; padding: 0; margin: 0; display: none; max-height: 40vh; overflow: auto; border: 1px solid var(--border); border-radius: 12px; background: #fff; }
		.sn-ul.active { display: block; }
		.sn-ul li { padding: 10px 12px; border-bottom: 1px solid var(--border); font-size: 14px; }
		.sn-ul li:last-child { border-bottom: 0; }

		.footer { margin-top: 16px; text-align: center; color: var(--muted); font-size: 12px; }
		.toast { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom)); transform: translateX(-50%); background: rgba(0,0,0,.8); color: #fff; padding: 10px 14px; border-radius: 999px; font-size: 13px; display: none; z-index: 9999; }
	</style>
</head>
<body>
	<div class="container">
		<div class="header">
			<div class="order">项目：<span id="projectId">-</span>	|	订单：<span id="orderNo">-</span></div>
			<button class="refresh-btn" id="refreshBtn">刷新</button>
		</div>

		<div id="orderListView" class="list"></div>
		<div id="listView" class="list" style="display:none"></div>

		<div id="detailView" class="detail">
			<div class="card" style="flex:1; width:100%">
				<div class="head">
					<button class="back" id="backToOrdersBtn">订单</button>
					<button class="back" id="backBtn">返回</button>
					<div class="code" id="skuCode">-</div>
					<div class="stat">
						<div>计划<b id="planQty">0</b></div>
						<div>已收<b id="receivedQty">0</b></div>
						<div>待收<b id="pendingQty">0</b></div>
					</div>
				</div>

				<div class="scan">
					<input id="snInput" type="text" inputmode="text" autocomplete="off" placeholder="扫码或输入SN，回车确认" />
					<button id="scanBtn">收货</button>
				</div>

				<div class="tabs">
					<div class="tab active" data-tab="received">已收货SN（<span id="receivedCount">0</span>）</div>
					<div class="tab" data-tab="pending">待收货SN（<span id="pendingCount">0</span>）</div>
				</div>

				<div class="sn-list">
					<ul id="receivedList" class="sn-ul active"></ul>
					<ul id="pendingList" class="sn-ul"></ul>
				</div>
			</div>
		</div>

<!--		<div class="footer">为移动端优化 · 支持扫码枪回车</div>-->
	</div>
	<div class="toast" id="toast"></div>

	<script>
		// 可配置：后端基础地址（通过 Nginx 反向代理建议使用 /api 前缀）
			const API_BASE = '/api'; // 如直连后端，可改为 'http://127.0.0.1:9004'
		const endpoints = {
			orders: (projectId) => `${API_BASE}/receive/orders?projectId=${encodeURIComponent(projectId)}`,
			list: (orderNo) => `${API_BASE}/receive/items?orderNo=${encodeURIComponent(orderNo)}`,
			item: (orderNo, skuCode) => `${API_BASE}/receive/item?orderNo=${encodeURIComponent(orderNo)}&skuCode=${encodeURIComponent(skuCode)}`,
			receive: () => `${API_BASE}/receive/scan`
		};

			const state = {
				projectId: '',
				orders: [],
				orderNo: '',
				items: [],
				current: null // { skuCode, planQty, receivedQty, pendingQty, receivedSNs:[], pendingSNs:[] }
			};

		function showToast(msg) {
			const t = document.getElementById('toast');
			t.textContent = msg;
			t.style.display = 'block';
			setTimeout(() => { t.style.display = 'none'; }, 1500);
		}

		function getQuery(name) {
			const url = new URL(location.href);
			return url.searchParams.get(name) || '';
		}

		async function fetchJSON(url, options) {
			try {
				const res = await fetch(url, options);
				if (!res.ok) throw new Error(`HTTP ${res.status}`);
				return await res.json();
			} catch (e) {
				console.error('请求失败', e);
				throw e;
			}
		}

			// Mock 数据（当后端未就绪时使用）
			function mockOrders(projectId) {
				return [
					{ orderNo: 'PO-202509-001', name: '订单一', supplier: '供应商A' },
					{ orderNo: 'PO-202509-002', name: '订单二', supplier: '供应商B' },
					{ orderNo: 'PO-202509-003', name: '订单三', supplier: '供应商C' }
				];
			}
		function mockList(orderNo) {
			return [
				{ skuCode: 'SKU-1001', name: '示例商品 A', planQty: 10, receivedQty: 3, pendingQty: 7 },
				{ skuCode: 'SKU-1002', name: '示例商品 B', planQty: 5, receivedQty: 5, pendingQty: 0 },
				{ skuCode: 'SKU-1003', name: '示例商品 C', planQty: 8, receivedQty: 2, pendingQty: 6 }
			];
		}
		function mockItem(orderNo, skuCode) {
			return {
				skuCode,
				planQty: 10,
				receivedQty: 3,
				pendingQty: 7,
				receivedSNs: ['A001','A002','A003'],
				pendingSNs: ['P004','P005','P006','P007','P008','P009','P010']
			};
		}

			async function loadOrders() {
				const listEl = document.getElementById('orderListView');
				listEl.innerHTML = '';
				try {
					const data = await fetchJSON(endpoints.orders(state.projectId));
					state.orders = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : []);
				} catch (e) {
					state.orders = mockOrders(state.projectId);
				}
				renderOrders();
			}

			function renderOrders() {
				const listEl = document.getElementById('orderListView');
				if (!state.orders.length) {
					listEl.innerHTML = `<div class="card">没有找到相关订单</div>`;
					return;
				}
				const frag = document.createDocumentFragment();
				state.orders.forEach(order => {
					const row = document.createElement('div');
					row.className = 'item';
					row.innerHTML = `
						<div>
							<div class="item-title">${order.name || '订单'}</div>
							<div class="item-sub">${order.orderNo}</div>
						</div>
						<div class="item-qty">
							<div style="white-space:nowrap;">供应商 <b>${order.supplier || '-'}</b></div>
						</div>
						<button class="item-enter">进入</button>
					`;
					row.querySelector('.item-enter').addEventListener('click', () => selectOrder(order.orderNo));
					row.addEventListener('click', (e) => {
						if (!(e.target instanceof HTMLButtonElement)) selectOrder(order.orderNo);
					});
					frag.appendChild(row);
				});
				listEl.appendChild(frag);
			}

			function selectOrder(orderNo) {
				state.orderNo = orderNo;
				document.getElementById('orderNo').textContent = orderNo || '-';
				document.getElementById('orderListView').style.display = 'none';
				document.getElementById('detailView').style.display = 'none';
				document.getElementById('listView').style.display = '';
				loadList();
			}

		async function loadList() {
			const orderNo = state.orderNo;
			const listEl = document.getElementById('listView');
			listEl.innerHTML = '';
			try {
				const data = await fetchJSON(endpoints.list(orderNo));
				state.items = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : []);
			} catch (e) {
				// 使用 mock
				state.items = mockList(orderNo);
			}
			renderList();
		}

		function renderList() {
			const listEl = document.getElementById('listView');
			if (!state.items.length) {
				listEl.innerHTML = `<div class="card">没有找到相关商品</div>`;
				return;
			}
			const frag = document.createDocumentFragment();
			state.items.forEach(item => {
				const row = document.createElement('div');
				row.className = 'item';
				row.innerHTML = `
					<div>
						<div class="item-title">${item.name || ''}</div>
						<div class="item-sub">${item.skuCode}</div>
					</div>
					<div class="item-qty">
						<div>计划 <b>${item.planQty ?? 0}</b></div>
						<div>已收 <b>${item.receivedQty ?? 0}</b></div>
						<div>待收 <b>${item.pendingQty ?? 0}</b></div>
					</div>
					<button class="item-enter">进入</button>
				`;
				row.querySelector('.item-enter').addEventListener('click', () => enterDetail(item.skuCode));
				row.addEventListener('click', (e) => {
					if (!(e.target instanceof HTMLButtonElement)) enterDetail(item.skuCode);
				});
				frag.appendChild(row);
			});
			listEl.appendChild(frag);
		}

		async function enterDetail(skuCode) {
			// 加载商品详情
			try {
				const data = await fetchJSON(endpoints.item(state.orderNo, skuCode));
				const d = data?.data || data || {};
				state.current = {
					skuCode: d.skuCode || skuCode,
					planQty: Number(d.planQty ?? 0),
					receivedQty: Number(d.receivedQty ?? 0),
					pendingQty: Number(d.pendingQty ?? Math.max(0, (d.planQty ?? 0) - (d.receivedQty ?? 0))),
					receivedSNs: Array.isArray(d.receivedSNs) ? d.receivedSNs : [],
					pendingSNs: Array.isArray(d.pendingSNs) ? d.pendingSNs : []
				};
			} catch (e) {
				state.current = mockItem(state.orderNo, skuCode);
			}
			document.getElementById('listView').style.display = 'none';
			document.getElementById('detailView').style.display = 'flex';
			renderDetail();
			setTimeout(() => document.getElementById('snInput').focus(), 50);
		}

		function renderDetail() {
			const cur = state.current;
			if (!cur) return;
			document.getElementById('skuCode').textContent = cur.skuCode;
			document.getElementById('planQty').textContent = cur.planQty;
			document.getElementById('receivedQty').textContent = cur.receivedQty;
			document.getElementById('pendingQty').textContent = cur.pendingQty;
			document.getElementById('receivedCount').textContent = cur.receivedSNs.length;
			document.getElementById('pendingCount').textContent = cur.pendingSNs.length;

			const rList = document.getElementById('receivedList');
			const pList = document.getElementById('pendingList');
			rList.innerHTML = '';
			pList.innerHTML = '';
			cur.receivedSNs.forEach(sn => {
				const li = document.createElement('li');
				li.textContent = sn;
				rList.appendChild(li);
			});
			cur.pendingSNs.forEach(sn => {
				const li = document.createElement('li');
				li.textContent = sn;
				pList.appendChild(li);
			});
		}

		async function submitSN() {
			const input = document.getElementById('snInput');
			const sn = input.value.trim();
			if (!sn) { showToast('请输入/扫码SN'); return; }
			if (!state.current) return;
			const btn = document.getElementById('scanBtn');
			btn.disabled = true; input.disabled = true;
			try {
				const payload = { orderNo: state.orderNo, skuCode: state.current.skuCode, sn };
				let ok = true;
				try {
					const res = await fetchJSON(endpoints.receive(), {
						method: 'POST',
						headers: { 'Content-Type': 'application/json' },
						body: JSON.stringify(payload)
					});
					// 假设后端返回 { code:0, msg:'', data:{receivedQty,pendingQty, receivedSNs, pendingSNs} }
					if (res && (res.code === 0 || res.success)) {
						applyServerDetail(res.data);
					} else {
						ok = false; showToast(res?.msg || '收货失败');
					}
				} catch (e) {
					// 本地模拟更新
					applyLocalReceive(sn);
				}
				if (ok) { showToast('收货成功'); input.value = ''; }
			} finally {
				btn.disabled = false; input.disabled = false; input.focus();
			}
		}

		function applyServerDetail(data) {
			if (!state.current) return;
			const cur = state.current;
			cur.receivedQty = Number(data?.receivedQty ?? cur.receivedQty);
			cur.pendingQty = Number(data?.pendingQty ?? Math.max(0, cur.planQty - cur.receivedQty));
			cur.receivedSNs = Array.isArray(data?.receivedSNs) ? data.receivedSNs : cur.receivedSNs;
			cur.pendingSNs = Array.isArray(data?.pendingSNs) ? data.pendingSNs : cur.pendingSNs;
			renderDetail();
			// 同步列表数量
			const it = state.items.find(x => x.skuCode === cur.skuCode);
			if (it) { it.receivedQty = cur.receivedQty; it.pendingQty = cur.pendingQty; }
		}

		function applyLocalReceive(sn) {
			if (!state.current) return;
			const cur = state.current;
			// 若在待收列表中，移到已收；若不在，直接加入已收
			const idx = cur.pendingSNs.indexOf(sn);
			if (idx >= 0) cur.pendingSNs.splice(idx, 1);
			if (!cur.receivedSNs.includes(sn)) cur.receivedSNs.unshift(sn);
			cur.receivedQty = Math.min(cur.planQty, cur.receivedQty + 1);
			cur.pendingQty = Math.max(0, cur.planQty - cur.receivedQty);
			renderDetail();
			const it = state.items.find(x => x.skuCode === cur.skuCode);
			if (it) { it.receivedQty = cur.receivedQty; it.pendingQty = cur.pendingQty; }
		}

		function bindEvents() {
				document.getElementById('refreshBtn').addEventListener('click', () => {
					if (state.projectId && !state.orderNo) return loadOrders();
					return loadList();
				});
			document.getElementById('backBtn').addEventListener('click', () => {
				document.getElementById('detailView').style.display = 'none';
				document.getElementById('listView').style.display = '';
			});
				document.getElementById('backToOrdersBtn').addEventListener('click', () => {
					state.current = null;
					document.getElementById('detailView').style.display = 'none';
					document.getElementById('listView').style.display = 'none';
					document.getElementById('orderListView').style.display = '';
				});
			document.getElementById('scanBtn').addEventListener('click', submitSN);
			document.getElementById('snInput').addEventListener('keydown', (e) => {
				if (e.key === 'Enter') submitSN();
			});
			document.querySelectorAll('.tab').forEach(tab => {
				tab.addEventListener('click', () => {
					document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
					tab.classList.add('active');
					document.querySelectorAll('.sn-ul').forEach(u => u.classList.remove('active'));
					document.getElementById(tab.dataset.tab === 'received' ? 'receivedList' : 'pendingList').classList.add('active');
				});
			});
		}

			async function init() {
				state.projectId = getQuery('projectId') || getQuery('projectid') || '';
				state.orderNo = getQuery('orderNo') || getQuery('orderno') || getQuery('order_no') || '';
				document.getElementById('projectId').textContent = state.projectId || '-';
				document.getElementById('orderNo').textContent = state.orderNo || '-';
				bindEvents();
				if (state.projectId && !state.orderNo) {
					document.getElementById('orderListView').style.display = '';
					document.getElementById('listView').style.display = 'none';
					document.getElementById('detailView').style.display = 'none';
					await loadOrders();
				} else if (state.orderNo) {
					document.getElementById('orderListView').style.display = 'none';
					document.getElementById('listView').style.display = '';
					await loadList();
				} else {
					document.getElementById('orderListView').style.display = '';
					document.getElementById('orderListView').innerHTML = `<div class="card">请通过 projectId 选择订单，或在 URL 传入 orderNo</div>`;
				}
			}

		init();
	</script>
</body>
</html>
